﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Input;

namespace ERModelData
{
    /// <summary>Холст - рабочее пространство</summary>
    class Canvas : System.Windows.Controls.Canvas
    {
        /// <summary>Объект трансформации сущности</summary>
        public Transformation transform { get; private set; }

        /// <summary>Конструктор класса</summary>
        /// <param name="property">Панель отражающая свойства объекта</param>
        public Canvas(Property property)
        {
            transform = new Transformation(property);

            ContextMenu CanvasMenu = new ContextMenu();
            
            Label addEssence = new Label();
            addEssence.Content = "Добавить сущность";
            addEssence.MouseLeftButtonUp += new MouseButtonEventHandler(AddEssense);
            CanvasMenu.Items.Add(addEssence);

            Label addLink = new Label();
            addLink.Content = "Добавить связь";
            addLink.MouseLeftButtonUp += new MouseButtonEventHandler(AddLink);
            CanvasMenu.Items.Add(addLink);

            /// Настройки Canvas
            this.Background = Brushes.WhiteSmoke;
            this.ContextMenu = CanvasMenu;
            EnableWorkMode();
        }

        /// <summary>[Event Handler] Создание новой сущности</summary>
        private void AddEssense(object sender, RoutedEventArgs e)
        {
            IsCreateEssenceMode = true;
            this.PreviewMouseLeftButtonDown += eMouseDown;
            
        }

        /// <summary>[Event Handler] Создание новой связи</summary>
        private void AddLink(object sender, RoutedEventArgs e)
        {
            IsCreateLinkMode = true;
            this.PreviewMouseLeftButtonDown += eMouseDown;
            this.PreviewMouseMove += eMouseMove;
        }

        ///////////////////////////////////////////////////////////////////////////////////
        //////          Функционал режимов создания сущностей и связей              ///////
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>Выделенная сущность</summary>
        private Essence select;

        /// <summary>[Key] Курсор попадает на маркер трансформации</summary>
        private bool markerSelected;

        /// <summary>Обновление Z индексов объектов на холсте</summary>
        private void UpdateZIndex()
        {
            int count = 0;
            foreach (UIElement i in this.Children)
                Canvas.SetZIndex(i, count++);
            Canvas.SetZIndex(select, count++);
            transform.UpdateZIndexMarkers(count);

        }

        /// <summary>[Event Handler] Выделение объекта</summary>
        void Select(object sender, MouseButtonEventArgs e)
        {
            select = null;
            markerSelected = false;
            VisualTreeHelper.HitTest(this, null, HitTestEssence, new PointHitTestParameters(e.GetPosition(this)));
            if (!markerSelected)
                if (select == null) transform.Hiden();
                else
                {
                    transform.Hiden();
                    UpdateZIndex();
                    transform.Show(select);
                }
        }

        /// <summary>[Service Function] Разбор Z массива объектов</summary>
        private HitTestResultBehavior HitTestEssence(HitTestResult result)
        {
            if (result.VisualHit is Essence)
            {
                select = (Essence)result.VisualHit;
                return HitTestResultBehavior.Stop;
            }
            if (result.VisualHit is Ellipse)
            {
                markerSelected = true;
                return HitTestResultBehavior.Continue;
            }
            return HitTestResultBehavior.Continue;
        }

        ///////////////////////////////////////////////////////////////////////////////////
        //////          Функционал режимов создания сущностей и связей              ///////
        ///////////////////////////////////////////////////////////////////////////////////

        private bool _isCreateEssenceMode;
        private bool _isCreateLinkMode;
        private bool _isWorkMode;
        public bool IsCreateEssenceMode
        {
            get { return _isCreateEssenceMode; }
            set { _isCreateEssenceMode = value; if (value)DisableWorkMode(); }
        }

        public bool IsCreateLinkMode
        {
            get { return _isCreateLinkMode; }
            set { _isCreateLinkMode = value; if (value)DisableWorkMode(); }
        }

        public bool IsWorkMode
        {
            get { return IsWorkMode; }
            set { if (value)EnableWorkMode(); }
        }

        /// <summary>Начальная позиция создания объекта</summary>
        private Point startPos;

        /// <summary>Контур будущего объекта</summary>
        private Rectangle border = new Rectangle();

        /// <summary>Отключение рабочего режима</summary>
        private void DisableWorkMode()
        {
            transform.Hiden();
            this.PreviewMouseLeftButtonDown -= Select;
            this.ContextMenu.Visibility = Visibility.Hidden;
        }

        /// <summary>Включение рабочего режима</summary>
        private void EnableWorkMode()
        {
            this.PreviewMouseLeftButtonDown += Select;
            this.ContextMenu.Visibility = Visibility.Visible;
            IsCreateEssenceMode = false;
            IsCreateLinkMode = false;
        }

        /// <summary>[Event Handler] Начало создания объекта</summary>
        private void eMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateEssenceMode)
            {
                border.Fill = Brushes.Transparent;
                border.Stroke = Brushes.Black;
                border.StrokeThickness = 2;
                Canvas.SetLeft(border, e.GetPosition(this).X);
                Canvas.SetTop(border, e.GetPosition(this).Y);
                this.Children.Add(border);
                startPos = e.GetPosition(this);
                this.Cursor = Cursors.Cross;
                this.PreviewMouseLeftButtonDown -= eMouseDown;
                this.PreviewMouseMove += eMouseMove;
                this.PreviewMouseLeftButtonUp += eMouseUp;
            }
            if (IsCreateLinkMode)
            {

            }
        }

        /// <summary>[Event Handler] Выполнение создания объекта</summary>
        private void eMouseMove(object sender, MouseEventArgs e)
        {

            if (IsCreateEssenceMode)
            {
                if (e.GetPosition(this).X < startPos.X)
                    Canvas.SetLeft(border, e.GetPosition(this).X);
                if (e.GetPosition(this).Y < startPos.Y)
                    Canvas.SetTop(border, e.GetPosition(this).Y);
                border.Width = Math.Abs(e.GetPosition(this).X - startPos.X);
                border.Height = Math.Abs(e.GetPosition(this).Y - startPos.Y);
            }
            if (IsCreateLinkMode)
            {


            }
        }

        /// <summary>[Event Handler] Окончание создания объекта</summary>
        private void eMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateEssenceMode)
            {
                this.Cursor = Cursors.Arrow;
                this.PreviewMouseMove -= eMouseMove;
                this.PreviewMouseLeftButtonUp -= eMouseUp;
                this.Children.Remove(border);
                this.Children.Remove(border);
                new Essence(
                    new Point(Canvas.GetLeft(border), Canvas.GetTop(border)),
                    new Size(border.Width, border.Height),
                    this);
                IsWorkMode = true;
            }
        }
        
    }
}
